#include "SypEngine.h"


#ifdef CHECKMEM
#include "mmgr.h"
#endif

namespace Syp
{
	void GuiBase::setColor(Syp::Color3f& color)
	{
		FloatArray& data = mesh->getDataRef();
		data[3] = color.r;
		data[4] = color.g;
		data[5] = color.b;

		data[11] = color.r;
		data[12] = color.g;
		data[13] = color.b;

		data[19] = color.r;
		data[20] = color.g;
		data[21] = color.b;

		data[27] = color.r;
		data[28] = color.g;
		data[29] = color.b;

		mesh->updateMesh();

	}	

	void GuiBase::setColor(Syp::Color3f &color_bl, Syp::Color3f &color_br, Syp::Color3f &color_tr, Syp::Color3f& color_tl)
	{
		FloatArray& data = mesh->getDataRef();
		data[3] = color_bl.r;
		data[4] = color_bl.g;
		data[5] = color_bl.b;

		data[11] = color_br.r;
		data[12] = color_br.g;
		data[13] = color_br.b;

		data[19] = color_tr.r;
		data[20] = color_tr.g;
		data[21] = color_tr.b;

		data[27] = color_tl.r;
		data[28] = color_tl.g;
		data[29] = color_tl.b;

		mesh->updateMesh();

	}

	void GuiBase::setUVCoord(float u1, float v1, float width, float height)
	{
		FloatArray& data = mesh->getDataRef();
		data[6] = u1;
		data[7] = v1;

		data[14] = u1 + width;
		data[15] = v1;

		data[22] = u1 + width;
		data[23] = v1 + height;

		data[30] = u1;
		data[31] = v1 + height;

		mesh->updateMesh();


	}

	void GuiBase::genMesh()
	{
		mat = Material::createMaterial(name + " Material");
		SubMaterial sm;
		sm.btype = NOBLEND;
		//we dont want the GUI to be affected by the lights
		sm.lit = false;
		sm.diffuse[0] = 1.0f;
		//sm.useTexture(TextureObj::loadTexture("Textures/font.png",false));
		//sm.useTexture(TextureObj::loadTexture(fileName,false));
		sm.useEffect("GuiFF");
		mat->subMaterials.push_back(sm);			

		mesh = NIndexedMesh::createNIndexedMesh(name + " Mesh", DYNAMIC);
		mesh->setVertexType(Syp::VC3T);
		mesh->setRenderingFormat(FORMAT_QUADS);
		IndexBlock ib;
		ib.materialID = 0;
		mesh->getDrawCallsRef().push_back(ib);
		mesh->getNumVerticesRef() = 4;

		mi = MeshInstance::createMeshInstance();
		mi->mode = ORTHO;
		mi->useMesh(mesh);
		mi->useMaterial(mat);



		FloatArray& data = mesh->getDataRef();
		data.resize(32);


		data[0] = 0.0f;
		data[1] = 0.0f;
		data[2] = 0.0f;
		data[3] = 1.0f;
		data[4] = 1.0f;
		data[5] = 1.0f;
		data[6] = 0.0f;
		data[7] = 0.0f;

		data[8] = width;
		data[9] = 0.0f;
		data[10] = 0.0f;
		data[11] = 1.0f;
		data[12] = 1.0f;
		data[13] = 1.0f;
		data[14] = 1.0f;
		data[15] = 0.0f;

		data[16] = width;
		data[17] = height;
		data[18] = 0.0f;
		data[19] = 1.0f;
		data[20] = 1.0f;
		data[21] = 1.0f;
		data[22] = 1.0f;
		data[23] = 1.0f;

		data[24] = 0.0f;
		data[25] = height;
		data[26] = 0.0f;
		data[27] = 1.0f;
		data[28] = 1.0f;
		data[29] = 1.0f;
		data[30] = 0.0f;
		data[31] = 1.0f;

		mesh->updateMesh();


	}
	bool GuiBase::isMouseIn()
	{
		return mouseIsIn;
	}

	void GuiBase::setMouseFocus(GuiBase* gb)
	{
		mouseFocus = gb;
	}
	GuiBase* GuiBase::getMouseFocus()
	{
		return mouseFocus;
	}

	GuiBase* GuiBase::mouseFocus = 0;

	GuiBase::GuiBase(const String& Name,float Width, float Height,bool genmesh):name(Name),width(Width),height(Height),mouseIsIn(false),mi(0),mesh(0),depressed(false)
	{
		if(genmesh)
		{
			genMesh();
		}



	}
	GuiBase::~GuiBase()
	{
		MeshInstance::destroyMeshInstance(mi);
	}
	MeshInstance& GuiBase::getMIRef()
	{
		return (*mi);
	}

	void GuiBase::destroyGuiComponent(GuiBase* gb)
	{
		delete gb;
	}

	void GuiBase::useTexture(const String& filename)
	{
		mat->subMaterials[0].useTexture(filename);
	}

	void GuiBase::useTexture(TextureObj* tex)
	{
		mat->subMaterials[0].useTexture(tex);
	}

	void GuiBase::mouseLeftDown()
	{
		GuiBase* inFocus = 0;		
		inFocus = GuiBase::getMouseFocus();
		if(inFocus == this || inFocus == 0)
		{//Nobody competing, its all ours
			GuiBase::setMouseFocus(this);
			depressed = true;//Was pressed on
		}
		else if(inFocus->mouseIsIn && inFocus->getMIRef().getPosition().z > getMIRef().getPosition().z)
		{//We have someone else fighting for it and they deserve to get signal over us
			
			return;
		}
		else
		{
				GuiBase::setMouseFocus(this);
				depressed = true;//Was pressed on			
		}
		

	}

	void GuiBase::mouseRightDown()
	{

	}

	void GuiBase::mouseLeftUp()
	{		
		

	}

	void GuiBase::mouseRightUp()
	{

	}

	bool GuiBase::isLeftDepressed()
	{
		return depressed;
	}

	void GuiBase::recieveMouseInfo(const MouseState& ms,MouseEvent me)
	{		
		const Point4& cPos = mi->getPosition();
		switch(me)
		{
		case MOUSEMOVE:			
			////////////////////////////////////////////////////////////////////////////////////////
			//Collission checking
			if(ms.mouseX < (cPos.x + width) && ms.mouseX > cPos.x &&
				ms.mouseY < (cPos.y + height) && ms.mouseY > cPos.y)
			{//mouse is in da house!
				if(!mouseIsIn)
				{//if it isnt already registered as in, set it and call mouseOver once
					mouseIsIn = true;
					if(depressed)
					{
						this->mouseLeftDown();
						onMouseLeftDown(this);
					}
					else
					{
						if( !ms.mouseLeft )
						{//if mouse is not depressed when it entered my realm
							this->mouseOver();
							onMouseOver(this);
						}
					}
				}//else nothing has changed

			}
			else//failed collission check, mouse not in
			{
				if(mouseIsIn)
				{//No longer in da house
					mouseIsIn = false;
					if(depressed)
					{
						this->mouseLeftUp();
						onMouseLeftUp(this);
					}
					else
					{
						this->mouseOut();
						onMouseOut(this);
					}
				}
			}////////////////////////////////////////////////////////////////////////////////////////////			

			//Stuff which is done regardless of whether mouse is within boundaries.
			///////////////////////////////////////GLOBAL ACTIONS///////////////////////////////////
			//Mouse move
			this->mouseMove(ms);
			onMouseMove(this);			
			break;
		case MOUSELEFTDOWN:
			if(mouseIsIn)
			{				
				this->mouseLeftDown();
				onMouseLeftDown(this);			
			}
			else
			{
				if(GuiBase::getMouseFocus() == this)
				{
					GuiBase::setMouseFocus(0);
				}

			}
			break;
		case MOUSELEFTUP:				
			if(mouseIsIn)
			{
				this->mouseLeftUp();
				onMouseLeftUp(this);	
				depressed = false;//no matter what as long as mouseUps, every motherson is not depressed
			}
			else
			{
				if( depressed )
				{
					this->mouseOut();
					onMouseOut(this);
					depressed = false;//no matter what as long as mouseUps, every motherson is not depressed
				}
			}
			
			break;
		case MOUSERIGHTDOWN:
			if(mouseIsIn)
			{
				this->mouseRightDown();
				onMouseRightDown(this);			
			}
			break;
		case MOUSERIGHTUP:		
			if(mouseIsIn)
			{
				this->mouseRightUp();
				onMouseRightUp(this);			
			}
			break;

		}

	}

}
